#ifndef VISIYUNDEVICE_H
#define VISIYUNDEVICE_H

#include <QObject>
#include <QVariant>
#include <QString>
#include <QtConcurrent>
#include <QMutex>
#include <QAtomicInt>
#include <functional>
#include <QImage>
#include <QTimer>
#include "CameraParametersWidget.h"
extern "C"{
#include "VsyCam_Lib.h"
}

// 设备参数名称宏定义（大驼峰命名）
#define PARAM_GAIN "Gain"                     // 增益
#define PARAM_SAMPLING_FREQUENCY "SamplingFrequency" // 采样频率
#define PARAM_EXPOSURE_TIME "ExposureTime"     // 曝光时间
#define PARAM_TRIGGER_MODE "TriggerMode"       // 触发模式
#define PARAM_TRIGGER_EDGE "TriggerEdge"       // 触发沿类型
#define PARAM_TRIGGER_CHANNEL "TriggerChannel" // 触发通道
/**
 * @brief 注册图像回调函数
 */
using ImageCallback = std::function<void(const QString&, const QImage&, int)>;

class VisiyunDevice : public QObject
{
    Q_OBJECT
public:
    explicit VisiyunDevice(const QString& deviceIp, QObject *parent = nullptr);
    ~VisiyunDevice() override;

    /**
     * @brief 打开设备连接
     * @return 连接成功返回true，失败返回false
     */
    bool open();

    /**
     * @brief 关闭设备连接
     */
    void close();

    /**
     * @brief 获取设备像素尺寸
     * @return 像素尺寸QSize(width, height)，失败返回空尺寸
     */
    QSize getPixelSize() const;

    /**
     * @brief 获取设备IP地址
     * @return 设备IP地址字符串
     */
    QString deviceIp() const { return m_deviceIp; }

    /**
     * @brief 检查设备是否已连接
     * @return 已连接返回true，否则返回false
     */
    bool isConnected() const { return m_isConnected; }

    /**
     * @brief 注册图像回调函数
     */
    void setImageCallback(ImageCallback callback);

    /**
     * @brief 启动图像采集
     * @return 启动成功返回true，失败返回false
     */
    bool startCapture();

    /**
     * @brief 停止图像采集
     */
    void stopCapture();
    /**
     * @brief 获取固件版本
     */
    int getFirmwareVersion() const;

    /**
     * @brief 获取设备增益值
     * @return 增益值，失败返回-1
     */
    quint64 getGain() const;

    /**
     * @brief 设置设备增益值
     * @param gain 增益值
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setGain(quint64 gain);

    /**
     * @brief 获取设备采样频率
     * @return 采样频率值(Hz)，失败返回-1
     */
    quint64 getSamplingFrequency() const;

    /**
     * @brief 设置设备采样频率
     * @param frequency 采样频率值(Hz)
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setSamplingFrequency(quint64 frequency);

    /**
     * @brief 获取设备曝光时间（纳秒）
     * @return 曝光时间值，失败返回-1
     */
    quint64 getExposureTime() const;

    /**
     * @brief 设置设备曝光时间
     * @param time 曝光时间值(纳秒)
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setExposureTime(quint64 time);

    /**
     * @brief 获取设备触发模式
     * @return 触发模式(0:内触发, 1:外触发)，失败返回-1
     */
    int getTriggerMode() const;

    /**
     * @brief 设置设备触发模式
     * @param mode 触发模式(0:内触发, 1:外触发)
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setTriggerMode(int mode);
    
    /**
     * @brief 获取设备触发沿类型
     * @return 触发沿类型(0:上升沿, 1:下降沿)，失败返回-1
     */
    int getTriggerEdge() const;
    
    /**
     * @brief 设置设备触发沿类型
     * @param edge 触发沿类型(0:上升沿, 1:下降沿)
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setTriggerEdge(int edge);
    
    /**
     * @brief 获取设备触发通道
     * @return 触发通道号，失败返回-1
     */
    int getTriggerChannel() const;
    
    /**
     * @brief 设置设备触发通道
     * @param channel 触发通道号
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setTriggerChannel(int channel);
    
    /**
     * @brief 获取设备曝光时间单位
     * @return 时间单位值
     */
    int getTimeUnit() const; 
    
    /**
     * @brief 获取设备增益单位
     * @return 增益单位值
     */
    int getGainUnit() const; 
    
    /**
     * @brief 获取设备采样频率单位
     * @return 频率单位值
     */
    int getFrequencyUnit() const; 
    
    /**
     * @brief 设置设备曝光时间单位
     * @param unit 时间单位值
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setTimeUnit(int unit); 
    
    /**
     * @brief 设置设备增益单位
     * @param unit 增益单位值
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setGainUnit(int unit); 
    
    /**
     * @brief 设置设备采样频率单位
     * @param unit 频率单位值
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setFrequencyUnit(int unit); 
    
    /**
     * @brief 获取设备最小增益值
     * @return 最小增益值
     */
    quint64 getMinGain() const; 
    
    /**
     * @brief 获取设备最大增益值
     * @return 最大增益值
     */
    quint64 getMaxGain() const; 
    
    /**
     * @brief 获取设备最小采样频率
     * @return 最小采样频率(Hz)
     */
    quint64 getMinFrequency() const; 
    
    /**
     * @brief 获取设备最大采样频率
     * @return 最大采样频率(Hz)
     */
    quint64 getMaxFrequency() const; 
    
    /**
     * @brief 获取设备最小曝光时间
     * @return 最小曝光时间(纳秒)
     */
    quint64 getMinExposureTime() const; 
    
    /**
     * @brief 获取设备最大曝光时间
     * @return 最大曝光时间(纳秒)
     */
    quint64 getMaxExposureTime() const; 
    
    /**
     * @brief 设置设备最小增益值
     * @param min 最小增益值
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setMinGain(quint64 min); 
    
    /**
     * @brief 设置设备最大增益值
     * @param max 最大增益值
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setMaxGain(quint64 max); 
    
    /**
     * @brief 设置设备最小采样频率
     * @param min 最小采样频率(Hz)
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setMinFrequency(quint64 min); 
    
    /**
     * @brief 设置设备最大采样频率
     * @param max 最大采样频率(Hz)
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setMaxFrequency(quint64 max); 
    
    /**
     * @brief 设置设备最小曝光时间
     * @param min 最小曝光时间(纳秒)
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setMinExposureTime(quint64 min); 
    
    /**
     * @brief 设置设备最大曝光时间
     * @param max 最大曝光时间(纳秒)
     * @return 操作结果，0表示成功，其他表示失败
     */
    int setMaxExposureTime(quint64 max);
    
    /**
     * @brief 初始化设备参数范围和单位
     * @return 初始化成功返回true，失败返回false
     */
    bool initializeDeviceParameters();
    
    /**
     * @brief 获取设备参数
     * @return 设备参数映射，使用QVariantMap作为万能变量类型
     */
    QVariantMap getParameters() const;
    
    /**
     * @brief 设置设备参数
     * @param params 设备参数映射，使用QVariantMap作为万能变量类型
     * @return 设置成功返回true，失败返回false
     */
    bool setParameters(const QVariantMap& params);
signals:
    /**
     * @brief 设备连接状态变化信号
     */
    void connectionStateChanged(bool connected);
    
private slots:
    /**
     * @brief 图像采集循环函数
     */
    void captureImages();
    /**
     * @brief 发送心跳
     */
    void sendBeatheart();

private:
    QString m_deviceIp;       // 设备IP地址
    int m_controlId;          // 设备控制ID
    int m_imageTransId;       //图像连接ID
    bool m_isConnected;       // 连接状态标志
    QFuture<void> m_captureFuture; // 采集任务Future
    QFutureWatcher<void> m_captureWatcher; // 采集任务监视器
    QAtomicInt m_running;     // 采集运行标志
    QMutex m_mutex;           // 线程同步锁
    ImageCallback m_callback; // 图像回调函数
    quint8* m_pRawBuf; // 原始图像缓冲区
    
    // 单位存储
    int m_timeUnit;           // 曝光时间单位
    int m_gainUnit;           // 增益单位
    int m_frequencyUnit;      // 采样频率单位
    
    // 参数范围存储
    quint64 m_minGain;         // 最小增益值
    quint64 m_maxGain;         // 最大增益值
    quint64 m_minFrequency;    // 最小采样频率
    quint64 m_maxFrequency;    // 最大采样频率
    quint64 m_minExposureTime; // 最小曝光时间
    quint64 m_maxExposureTime; // 最大曝光时间
    qint32 m_TriggerMode;     //触发模式
    qint32 m_ExternalTriggerChannel; // 外触发通道
    qint32 m_TriggerEdgeType; // 触发沿类型

    QTimer m_BeatheartTimer;  //心跳定时器
};

#endif // VISIYUNDEVICE_H
